#include <boost/lexical_cast.hpp>

#include "viewer.h"
#include "CImg.h"

namespace fc
{

using namespace cimg_library;
using namespace boost;

Viewer::Viewer(FuzzyClassifier& fuzzy_classifier) :
        fuzzyClassifier_(fuzzy_classifier)
{
    setsImage_ = CImg<unsigned char>(800, 100 * fuzzy_classifier.attributes_, 1, 3);
    vector< vector<FuzzySet> > &sets = fuzzy_classifier.sets_;
    int index = 0;
    for (vector< vector<FuzzySet> >::const_iterator setIt = sets.begin(); 
         setIt != sets.end(); ++setIt, ++index)
    {
        drawSets(*setIt, index);
    }
}

void Viewer::drawSets(const vector<FuzzySet>& sets, int index)
{
    CImg<unsigned char> setsImg(800, 100, 1, 3);
    const int interval = 800 / (sets.size() - 1);
    int offset = -interval;
    const unsigned char color[] = { 0xFF, 0xFF, 0xFF };
    setsImg.fill(0);
    setsImg.draw_line(0, 80, 800, 80, color);
    for (vector<FuzzySet>::const_iterator it = sets.begin(); it != sets.end(); ++it)
    {
        setsImg.draw_line(offset, 80, offset + interval, 0, color)
        .draw_line(offset + interval, 0, offset + 2 * interval, 80, color);
        offset += interval;
    }
    setsImage_.draw_image<unsigned char>(0, index * 100, setsImg);
}

void Viewer::show()
{
    CImgDisplay display(setsImage_, "Zbiory rozmyte");
    while (!display.is_closed())
    {
        display.wait();
        display.display(fillDecoration(display.mouse_x(), display.mouse_y()));
    }
}

cimg_library::CImg< unsigned char > Viewer::fillDecoration(int x, int y) const
{
    CImg< unsigned int > image(setsImage_);
    int attrNr = y / 100;
    double min = fuzzyClassifier_.min_[attrNr];
    double max = fuzzyClassifier_.max_[attrNr];
    double value = min + ((double)x / 800) * (max - min);
    const vector<FuzzySet> & sets = fuzzyClassifier_.sets_[attrNr];
    
    const int interval = 800 / (sets.size() - 1);
    int offset = -interval;
    
    int height = 0;
    double membership = 0;
    for (vector<FuzzySet>::const_iterator it = sets.begin(); it != sets.end(); ++it)
    {
        double membershipTmp = it->membership(value);
        int heightTmp = 80 * membershipTmp;
        if(height < heightTmp)
        {
            height = heightTmp;
            membership = membershipTmp;
        }
        offset += interval;
    }
    const unsigned char lineColor[] = { 0xAA, 0x11, 0x11 };
    const unsigned char textBg[] = { 0x11, 0x11, 0x11 };
    const unsigned char textFg[] = { 0xBB, 0xBB, 0xBB };
    
    string valueText = "value: " + lexical_cast<string>(value);
    string membText = "membership: " + lexical_cast<string>(membership);
    
    return image.draw_line(x, attrNr * 100 + 80, x, attrNr * 100 + 80 - height, lineColor).
        draw_text(5, 5, valueText.c_str(), textFg, textBg).
        draw_text(5, 20, membText.c_str(), textFg, textBg);
}


}
